home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Free Software Collection 10
/
FM Towns Free Software Collection 10.iso
/
ms_dos
/
lib
/
happysrc
/
piinst.c
< prev
next >
Wrap
Text File
|
1994-11-13
|
32KB
|
1,182 lines
/************************************************
**
** *** HAPPy P-code Interpreter ***
**
** P-code命令解釈実行処理
**
** Copyright (c) H.Asano. 1992-1994.
************************************************/
#define EXTERN extern
#define trans(reg) \
((unsigned short)(reg)-(unsigned short)(store))/sizeof(_store)
#define setlow 0
#define sethigh 31
#include <process.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "hapai.h"
extern void prerr(short,char*); /* Run-timeエラーメッセージ出力処理 */
extern void puteoln(void) ; /* ファイルクローズ時のeoln付与処理 */
extern void T_get(fileinfo*,_store*,char*); /* 1文字読込 */
extern void EOL(void) ;
extern void EoF(void) ;
extern void GET(void) ;
extern void PGE(void) ;
extern void PUT(void) ;
extern void RLN(void) ;
extern void RDC(void) ;
extern void RDI(void) ;
extern void RDR(void) ;
extern void RST(void) ;
extern void RWT(void) ;
extern void TGT(void) ;
extern void TPT(void) ;
extern void TRS(void) ;
extern void TRW(void) ;
extern void WLN(void) ;
extern void WRB(void) ;
extern void WRC(void) ;
extern void WRF(void) ;
extern void WRI(void) ;
extern void WRR(void) ;
extern void WRS(void) ;
/**********************************************/
/*** P-code 計算機のレジスタ、メモリその他 ***/
/**********************************************/
extern _store store[] ; /* 記憶装置 */
extern _code cd ; /* p-code */
extern _store *sp ; /* sp points to top of the stack */
extern short pc ; /* program counter */
extern short mp ; /* mp points to begginning of a data segment */
extern short ep ; /* ep points to the maxmum extent of the stack */
extern short np ; /* np points to top of the heap area */
extern boolean trace ; /* 命令トレースフラグ */
extern boolean readlnflag ; /* 起動時及びinputにreadlnをした時 真 */
/******** Run Time Error Mesage(埋め込み要のもの) **********/
static const struct {
short errno ;
char *msg ;
} errtbl[] = {
{ 1, "配列の添え字式の値(%ld)が範囲内(%ld~%ld)にない"},
{ 7, "実値引数の値(%ld)が範囲内(%ld~%ld)にない"},
{ 8, "実値引数の集合値が範囲内(%ld~%ld)にない"},
{ 17, "read: バッファ変数の値(%d)が範囲内(%ld~%ld)にない"},
{ 18, "write: 式の値(%ld)が範囲内(%ld~%ld)にない"},
{ 26, "pack: 順序型の引数の値(%ld)が範囲内(%ld~%ld)にない"},
{ 29, "unpack: 順序型の引数の値(%ld)が範囲内(%ld~%ld)にない"},
{ 31, "unpack: 転送後に詰めなし配列の添え字型を越える"},
{ 38, "succ: 引数の順序数(%ld)より1つ大きい値が存在しない"},
{ 39, "pred: 引数の順序数(%ld)より1つ小さい値が存在しない"},
{ 49, "代入文: 右辺値(%ld)が範囲内(%ld~%ld)にない"},
{ 50, "代入文: 集合値が範囲内(%ld~%ld)にない"},
{ 51, "case文: 選択式の値(%ld)に合致する選択定数がない"},
{ 52, "for文: 初期値(%ld)が範囲内(%ld~%ld)にない"},
{ 53, "for文: 終値(%ld)が範囲内(%ld~%ld)にない"},
{ 71, "read: 集合型のバッファ変数の値が範囲内(%ld~%ld)にない"},
{ 72, "write: 集合型の式の値が範囲内(%ld~%ld)にない"},
{111, "集合構成子の順序式の値(%ld)がHAPPyの制限範囲内(%ld~%ld)にない"}
} ;
/***************************************/
/* base() : 局所的番地を求める */
/***************************************/
static short base(void)
{
short ad ;
short ld ;
if(cd.p==0) return(mp) ; /* pが0ならmp値を返す */
ad = mp ;
ld = cd.p ;
while((ld--)) /* 0より大きい間繰り返し */
ad = store[ad+1].va ; /* static link */
return(ad) ;
}
/***************************************/
/* StrComp() : 文字列の比較を行う */
/***************************************/
static short StrComp(_store *str1,_store *str2,short length)
{
register _store *s1,*s2 ;
short disp ;
s1 = str1 ;
s2 = str2 ;
while(length--) {
disp = s1++->vc - s2++->vc ;
if(disp) return(disp) ;
}
return(0) ; /* s1とs2が同じ */
}
/************************ 各P-code の 処理 ****************************/
/******************/
/* ABI */ /* absolute integers */
/******************/
static void ABI(void)
{
(*sp).vi = labs((*sp).vi) ;
}
/******************/
/* ABR */ /* absolute reals */
/******************/
static void ABR(void)
{
(*sp).vr = (float)fabs((double)(*sp).vr);
}
/******************/
/* ADI */ /* add integers */
/******************/
static void ADI(void)
{
sp->vi += (sp--)->vi ;
}
/******************/
/* ADR */ /* add reals */
/******************/
static void ADR(void)
{
sp-- ;
(*sp).vr += (*(sp+1)).vr ;
}
/******************/
/* AND */ /* logical and */
/******************/
static void AND(void)
{
sp-- ;
(*sp).vb = (*sp).vb && (*(sp+1)).vb ;
}
/**************************************/
/* ATN() : arctan標準関数 */
/**************************************/
static void ATN(void)
{
(*sp).vr = (float)atan((double)(*sp).vr);
}
/******************/
/* BAS */ /* load base mark */
/******************/
static void BAS(void)
{
(*++sp).va = base() ;
}
/*****************/
/* CHK */
/*****************/
static void CHK(void)
{
short i ;
char buf[80] ;
if(((*sp).vi < store[cd.q-1].vi) ||
((*sp).vi > store[cd.q].vi)) {
i = -1 ;
while(errtbl[++i].errno != cd.p) ;
sprintf(buf,errtbl[i].msg,
(*sp).vi, store[cd.q-1].vi,store[cd.q].vi) ;
prerr(cd.p,buf) ; /* エラーメッセージ出力 */
}
}
/******************/
/* CHKs */ /* check set */
/******************/
static void CHKs(void)
{
short i ;
long s = 0 ; /* 集合 */
char buf[80] ;
for(i=(short)store[cd.q-1].vi;i<=(short)store[cd.q].vi;i++)
addset(s,i);
s = (~s & (*sp).vs) ;
if(s != 0) {
i = -1 ;
while(errtbl[++i].errno != cd.p) ;
sprintf(buf,errtbl[i].msg,
store[cd.q-1].vi,store[cd.q].vi) ;
prerr(cd.p,buf) ; /* エラーメッセージ出力 */
}
}
/******************/
/* CHR */ /* convert character */
/******************/
static void CHR(void)
{
char buf[80] ;
if(((*sp).vi < 0L) || (255L < (*sp).vi)) {
sprintf(buf,"chr: 引数の値(%ld)に対応する文字がない",(*sp).vi);
prerr(9,buf) ;
}
/* integer と char エリアは 0~255の範囲では同一なので変換不要 */
}
/******************/
/* CKA */ /* Check Address */
/******************/
static void CKA(void)
{
if((*sp).va == NilValue)
prerr(3,"対象変数のポインタ変数の値がnilである") ;
if(!((np <= (*sp).va) && ((*sp).va < Maxstore)))
prerr(4,"対象変数のポインタ変数の値が不定である") ;
}
/**************************************/
/* COS() : cos標準関数 */
/**************************************/
static void COS(void)
{
(*sp).vr = (float)cos((double)(*sp).vr) ;
}
/******************/
/* CUI */ /* Call User procedure Indirect */
/******************/
static void CUI(void)
{
short calladr ;
calladr = (*sp--).va ; /* 実行開始アドレス取得 */
mp= trans(sp) - (cd.p+4) ; /* 4はmstと関係 */
store[mp+4].va = pc ; /* 戻り番地 */
pc = calladr ; /* jump */
}
/******************/
/* CUP */ /* Call User Procedure */
/******************/
static void CUP(void)
{
mp =trans(sp) - (cd.p+4) ; /* 4はmstと関係*/
store[mp+4].va = pc ; /* 戻り番地 */
pc = cd.q ; /* jump */
}
/******************/
/* DEC */
/******************/
static void DEC(void)
{
if(cd.p==1) (*sp).vi -= cd.q ; /* 1(i) */
else (*sp).vc -= cd.q ; /* 0(a) 3(b) 6(c) */
/* ↑ boolean,char,addressエリアは同一 */
}
/******************/
/* DIF */
/******************/
static void DIF(void)
{
sp--;
(*sp).vs &= ((*sp).vs ^ (*(sp+1)).vs) ;
}
/**************************************/
/* DIS() : dispose標準手続き */
/**************************************/
static void DIS(void)
{
short ad ;
ad = (*sp--).va ; /* 解放するアドレス */
if(ad == NilValue)
prerr(23,"dispose: 引数の値がnilである") ;
if((np <= ad) && (ad < Maxstore)) { /* 正常値 */
if(ad == np) np += cd.q ; /* 一番後にnewした時だけ*/
/* 本当に解放する */
}
else prerr(24,"dispose: 引数の値が不定である") ;
}
/******************/
/* DVI */
/******************/
static void DVI(void)
{
if((*sp--).vi == 0) prerr(45,"div演算子: 0で割ろうとしている") ;
(*sp).vi /= (*(sp+1)).vi ;
}
/******************/
/* DVR */
/******************/
static void DVR(void)
{
if((*sp--).vr == (float)0.0)
prerr(44,"/演算子: 0で割ろうとしている") ;
(*sp).vr /= (*(sp+1)).vr ;
}
/******************/
/* EJP */ /* Extra block Jump */
/******************/
static void EJP(void)
{
short req ;
req = base() ;
while(mp != req) { /* スタックの枠を解放 */
sp = store + mp - 1 ;
ep = store[mp+3].va ; /* mp+3 ・・・ 旧ep */
mp = store[mp+2].va ; /* mp+2 ・・・ 動鎖 */
}
pc = cd.q;
}
/******************/
/* ENT */
/******************/
static void ENT(void)
{
sp = store + mp + cd.q - 1 ; /* スタックポインタ設定 */
if((ep = trans(sp)+cd.p) >= np) /* スタックの枠限界設定
& スタックチェック */
prerr(122,"スタック用のメモリが不足している") ;
}
/******************/
/* EQU */
/******************/
static void EQU(void)
{
sp-- ;
switch(cd.p) {
case 1: /* (*sp).vb = (*sp).vi == (*(sp+1)).vi ; return; */
case 2: /* (*sp).vb = (*sp).vr == (*(sp+1)).vr ; return; */
case 4: (*sp).vb = (*sp).vs == (*(sp+1)).vs ; return;
case 6: /* (*sp).vb = (*sp).vc == (*(sp+1)).vc ; return; */
case 0: /* (*sp).vb = (*sp).va == (*(sp+1)).va ; return; */
case 3: (*sp).vb = (*sp).vb == (*(sp+1)).vb ; return;
case 5: (*sp).vb = (StrComp(store+(*sp).va,
store+(*(sp+1)).va,
cd.q) == 0);
}
}
/**************************************/
/* EXP() : exp標準関数 */
/**************************************/
static void EXP(void)
{
(*sp).vr = (float)exp((double)(*sp).vr) ;
}
/******************/
/* FJP */
/******************/
static void FJP(void)
{
if(! (*(sp--)).vb) pc = cd.q;
}
/******************/
/* FLO */
/******************/
static void FLO(void)
{
(*(sp-1)).vr = (float)(*(sp-1)).vi ;
}
/******************/
/* FLT */
/******************/
static void FLT(void)
{
(*sp).vr = (float)(*sp).vi ;
}
/******************/
/* GEQ */
/******************/
static void GEQ(void)
{
sp-- ;
switch(cd.p) {
case 1: (*sp).vb = (*sp).vi >= (*(sp+1)).vi ; return;
case 2: (*sp).vb = (*sp).vr >= (*(sp+1)).vr ; return;
case 6: /* (*sp).vb = (*sp).vc >= (*(sp+1)).vc ; return; */
case 3: (*sp).vb = (*sp).vb >= (*(sp+1)).vb ; return;
case 4: (*sp).vb = !
((*(sp+1)).vs & ((*(sp+1)).vs ^ (*sp).vs)) ; return;
case 5: (*sp).vb = (StrComp(store+(*sp).va,
store+(*(sp+1)).va,
cd.q) >= 0);
}
}
/******************/
/* GRT */
/******************/
static void GRT(void)
{
sp-- ;
switch(cd.p) {
case 1: (*sp).vb = (*sp).vi > (*(sp+1)).vi ; return;
case 6: /* (*sp).vb = (*sp).vc > (*(sp+1)).vc ; return; */
case 3: (*sp).vb = (*sp).vb > (*(sp+1)).vb ; return;
case 2: (*sp).vb = (*sp).vr > (*(sp+1)).vr ; return;
case 5: (*sp).vb = (StrComp(store+(*sp).va,
store+(*(sp+1)).va,
cd.q) > 0);
}
}
/******************/
/* INC */
/******************/
static void INC(void)
{
if(cd.p==1) (*sp).vi += cd.q ; /* 1(i) */
else (*sp).vc += cd.q ; /* 0(a) 3(b) 6(c) */
/* ↑ boolean,char,addressエリアは同一 */
}
/******************/
/* IND */ /* INDirect */
/******************/
static void IND(void)
{
(*sp)=store[(*sp).va+cd.q] ;
}
/******************/
/* INDa */ /* INDirect address */
/******************/
static void INDa(void)
{
(*sp).va=store[(*sp).va+cd.q].va ;
}
#define INDb INDa
#define INDs IND
#define INDr IND
/******************/
/* INDc */ /* INDirect character */
/******************/
/* inputバッファの値が決まっていない時のために
特別な処理が必要なので、この処理を作りました */
static void INDc(void)
{
short adr ;
adr = (*sp).va+cd.q ;
if((adr == fi[0].fileadr) && readlnflag) {
T_get(fi,store+adr,"get");
readlnflag = false ;
}
(*sp).vc = store[adr].vc ;
}
/******************/
/* INN */
/******************/
static void INN(void)
{
integer i;
i=(*(--sp)).vi ;
(*sp).vb =
(i & 0xffffffe0) /* 0<=i<=31 かどうかの判定 */
? (boolean)false
: (boolean)(((*(sp+1)).vs >> (char)i) & 0x1) ;
}
/******************/
/* INT */
/******************/
static void INT(void)
{
sp--;
(*sp).vs &= (*(sp+1)).vs ;
}
/******************/
/* IOR */ /* logical inclusive or */
/******************/
static void IOR(void)
{
sp-- ;
(*sp).vb = (*sp).vb || (*(sp+1)).vb ;
}
/******************/
/* IXA */
/******************/
static void IXA(void)
{
short disp ;
disp = (short)((*sp--).vi - store[cd.q-1].vi);/* 配列の下限値を引く*/
(*sp).va += store[cd.q].va * disp ;
/* ↑ vaは2バイトエリアとて使用 */
}
/******************/
/* LAO */ /* load base-level address */
/******************/
static void LAO(void)
{
(*(++sp)).va = cd.q ;
}
/******************/
/* LAP */ /* Load Address Procedure */
/******************/
#define LAP LAO
/******************/
/* LCA */
/******************/
#define LCA LAO
/******************/
/* LCI */ /* load constant integer */
/******************/
#define LCI LDO
/******************/
/* LDA */ /* load level p address */
/******************/
static void LDA(void)
{
(*(++sp)).va = base()+cd.q ;
}
/******************/
/* LDC */ /* load constant */
/******************/
static void LDC(void)
{
sp++ ;
switch(cd.p) {
case 1 : (*sp).vi = cd.q; return ; /* integer */
case 6 : /* (*sp).vc = cd.q; return ; */ /* char */
case 3 : (*sp).vb = cd.q; return ; /* boolean */
case 2 : /* (*sp).vr = store[cd.q].vr; return;*//* real */
case 4 : *sp = store[cd.q]; return; /* set */
case 0 : (*sp).va = NilValue ; /* nil */
/* programmer が 生成できない値 */
}
}
/******************/
/* LDO */ /* load contents of base-level address */
/******************/
static void LDO(void)
{
*(++sp)=store[cd.q] ;
}
/******************/
/* LDOc */ /* load char of base-level address */
/******************/
/* inputバッファの値が決まっていない時のために
特別な処理が必要なので、この処理を作りました */
static void LDOc(void)
{
if((cd.q == fi[0].fileadr) && readlnflag) {
T_get(fi,store+cd.q,"get");
readlnflag = false ;
}
(*(++sp)).vc = store[cd.q].vc ;
}
/******************/
/* LDOa */ /* load char of base-level address */
/******************/
static void LDOa(void)
{
(*(++sp)).va = store[cd.q].va ;
}
#define LDOb LDOa
#define LDOr LDO
#define LDOs LDO
/******************/
/* LEQ */
/******************/
static void LEQ(void)
{
sp-- ;
switch(cd.p) {
case 1: (*sp).vb = (*sp).vi <= (*(sp+1)).vi ; return;
case 2: (*sp).vb = (*sp).vr <= (*(sp+1)).vr ; return;
case 6: /* (*sp).vb = (*sp).vc <= (*(sp+1)).vc ; return; */
case 3: (*sp).vb = (*sp).vb <= (*(sp+1)).vb ; return;
case 4: (*sp).vb = !
((*sp).vs & ((*sp).vs ^ (*(sp+1)).vs)) ; return;
case 5: (*sp).vb = (StrComp(store+(*sp).va,
store+(*(sp+1)).va,
cd.q) <= 0);
}
}
/******************/
/* LES */
/******************/
static void LES(void)
{
sp-- ;
switch(cd.p) {
case 1: (*sp).vb = (*sp).vi < (*(sp+1)).vi ; return;
case 2: (*sp).vb = (*sp).vr < (*(sp+1)).vr ; return;
case 6: /* (*sp).vb = (*sp).vc < (*(sp+1)).vc ; return; */
case 3: (*sp).vb = (*sp).vb < (*(sp+1)).vb ; return;
case 5: (*sp).vb = (StrComp(store+(*sp).va,
store+(*(sp+1)).va,
cd.q) < 0);
}
}
/******************/
/* LOD */ /* load contents of address at level p */
/******************/
static void LOD(void)
{
*(++sp) = store[base()+cd.q] ;
}
/******************/
/* LODa */ /* load contents of address at level p */
/******************/
static void LODa(void)
{
(*(++sp)).va = store[base()+cd.q].va ;
}
#define LODc LODa
#define LODb LODa
#define LODs LOD
#define LODr LOD
/**************************************/
/* LOG() : ln標準関数 */
/**************************************/
static void LOG(void)
{
if((*sp).vr <= (float)0.0)
prerr(33,"ln: 引数の値が0以下である") ;
(*sp).vr = (float)log((double)(*sp).vr);
}
/******************/
/* MMS */ /* Make Multiple Set */
/******************/
/* この命令だけが -dオプション指定時 自前でチェックを行っている。
統一がとれていないけど 暫定的処置である */
static void MMS(void)
{
long s = 0;
short i ;
long low,high ; /* 下限 上限 */
char buf[80] ;
sp-- ;
if(cd.p<=1) { /* p in [0,1] */
low = sp->vi ;
high = (sp+1)->vi ;
}
else { /* p in [2,3] */
low = (sp+1)->vi ;
high = sp->vi ;
}
if(cd.p & 0x1) /* p in [1,3] (-dオプション) */
if((low <= high) && /* 下限の方が大きい・・・要素なし*/
(((long)setlow > low) || (high > (long)sethigh))) {
sprintf(buf,
"集合: 式..式の値ががHAPPyの制限範囲内(%d~%d)にない",
setlow,sethigh) ;
prerr(112,buf) ; /* エラーメッセージ出力 */
}
for(i=(short)low;i<=(short)high;i++) addset(s,(short)i);
(*sp).vs = s;
}
/******************/
/* MOD */
/******************/
static void MOD(void)
{
if((*sp--).vi <= 0)
prerr(46,"mod演算子: 右辺値が0または負である") ;
(*sp).vi %= (*(sp+1)).vi ;
}
/******************/
/* MOV */
/******************/
static void MOV(void)
{
if(cd.p==1) /* 通常 */
memcpy(store+(sp-1)->va,
store+sp->va, cd.q*sizeof(_store)) ;
else /* cd.p==2 */ /* pack,unpack,writeの時使う */
memcpy(store+sp->va,
store+(sp-1)->va, cd.q*sizeof(_store)) ;
sp-=2 ;
}
/******************/
/* MPI */
/******************/
static void MPI(void)
{
sp--;
(*sp).vi *= (*(sp+1)).vi ;
}
/******************/
/* MPR */
/******************/
static void MPR(void)
{
sp--;
(*sp).vr *= (*(sp+1)).vr ;
}
/******************/
/* MSI */ /* Mark Stack Indirect */
/******************/
static void MSI(void)
{
(*(sp+2)).va = (*(sp--)).va ; /* 静鎖 */
(*(sp+3)).va = mp ; /* 動鎖 */
(*(sp+4)).va = ep ; /* 旧ep */
sp += 5 ;
}
/******************/
/* MST */ /* Mark STack */
/******************/
static void MST(void)
{
(*(sp+2)).va = base() ; /* 静鎖 */
(*(sp+3)).va = mp ; /* 動鎖 */
(*(sp+4)).va = ep ; /* 旧ep */
sp += 5 ;
}
/******************/
/* NEQ */
/******************/
static void NEQ(void)
{
sp-- ;
switch(cd.p) {
case 1: /* (*sp).vb = (*sp).vi != (*(sp+1)).vi ; return; */
case 2: /* (*sp).vb = (*sp).vr != (*(sp+1)).vr ; return; */
case 4: (*sp).vb = (*sp).vs != (*(sp+1)).vs ; return;
case 0: /* (*sp).vb = (*sp).va != (*(sp+1)).va ; return; */
case 6: /* (*sp).vb = (*sp).vc != (*(sp+1)).vc ; return; */
case 3: (*sp).vb = (*sp).vb != (*(sp+1)).vb ; return;
case 5: (*sp).vb = (StrComp(store+(*sp).va,
store+(*(sp+1)).va,
cd.q) != 0);
}
}
/**************************************/
/* NEW() : new標準手続き */
/**************************************/
static void NEW(void)
{
short ad ;
np -= cd.q ;
if(np <= ep)
prerr(121,"new: メモリ不足で割り付けができない") ;
ad = (*sp--).va ;
store[ad].va = np ;
}
/******************/
/* NGI */
/******************/
static void NGI(void)
{
(*sp).vi = - (*sp).vi ;
}
/******************/
/* NGR */
/******************/
static void NGR(void)
{
(*sp).vr = - (*sp).vr ;
}
/******************/
/* NOT */
/******************/
static void NOT(void)
{
(*sp).vb = ! (*sp).vb ;
}
/******************/
/* NXT */ /* next */ /* for ~ to */
/******************/
static void NXT(void)
{
if(cd.p==1) store[mp+cd.q].vi++ ;
else store[mp+cd.q].vc++ ; /* 3(b) 6(c) */
/* ↑ char と boolean は 同じエリア */
}
/******************/
/* NXD */ /* next downto */ /* for ~ downto */
/******************/
static void NXD(void)
{
if(cd.p==1) store[mp+cd.q].vi-- ;
else store[mp+cd.q].vc-- ; /* 3(b) 6(c) */
/* ↑ char と boolean は 同じエリア */
}
/******************/
/* ODD */
/******************/
static void ODD(void)
{
(*sp).vb = (boolean)((*sp).vi & 0x00000001) ;
}
/******************/
/* ORD */ /* ORDinary */
/******************/
static void ORD(void)
{
/* vc も vb も同じエリアなのでif文不要 */
/*if(cd.p == 3)*/ /* ordb */
(*sp).vi = (integer)(*sp).vb ;
/*else*/ /* ordc */
/*(*sp).vi = (integer)(*sp).vc ;*/
}
/******************/
/* RET */
/******************/
static void RET(void)
{
if(cd.p==0) sp = store + mp -1 ; /* retp:p=0 p<>0は以下の命令 */
else sp = store + mp ; /* reti,retr,retc,retb,rets */
pc = store[mp+4].va ; /* pc 復帰 */
ep = store[mp+3].va ; /* ep 復帰 */
mp = store[mp+2].va ; /* mp 復帰 */
}
/******************/
/* ROU */ /* round */
/******************/
static void ROU(void)
{
(*sp).vi = (integer)floor((double)((*sp).vr + 0.5)) ;
}
/******************/
/* SBI */ /* subtruct integers */
/******************/
static void SBI(void)
{
sp->vi -= (sp--)->vi ;
}
/******************/
/* SBR */ /* subtruct reals */
/******************/
static void SBR(void)
{
sp-- ;
(*sp).vr -= (*(sp+1)).vr ;
}
/******************/
/* SGS */
/******************/
static void SGS(void)
{
long s = 0 ;
addset(s,(short)(*sp).vi) ;
(*sp).vs = s ;
}
/***************************************/
/* SIN() : sin標準関数 */
/***************************************/
static void SIN(void)
{
(*sp).vr = (float)sin((double)(*sp).vr) ;
}
/******************/
/* SQI */
/******************/
static void SQI(void)
{
(*sp).vi *= (*sp).vi ;
}
/******************/
/* SQR */
/******************/
static void SQR(void)
{
(*sp).vr *= (*sp).vr ;
}
/***************************************/
/* SQT() : sqrt標準関数 */
/***************************************/
static void SQT(void)
{
if((*sp).vr < (float)0.0) /* 負の平方根 */
prerr(34,"sqrt:引数の値が負である") ;
(*sp).vr = (float)sqrt((double)(*sp).vr);
}
/******************/
/* SRO */ /* store at base-level address */
/******************/
static void SRO(void)
{
store[cd.q] = *(sp--) ;
}
/******************/
/* SROa */ /* store at base-level address */
/******************/
static void SROa(void)
{
store[cd.q].va = (*(sp--)).va ;
}
#define SROc SROa
#define SROb SROa
#define SROr SRO
#define SROs SRO
/******************/
/* STO */
/******************/
static void STO(void)
{
store[(*(sp-1)).va] = *sp ;
sp-=2 ;
}
/******************/
/* STOa */
/******************/
static void STOa(void)
{
store[(*(sp-1)).va].va = (*sp).va ;
sp-=2 ;
}
#define STOc STOa
#define STOb STOa
#define STOr STO
#define STOs STO
/******************/
/* STP */ /* stop */
/******************/
static void STP(void)
{
puteoln() ; /* ファイルクローズ & eoln付与*/
exit(0) ;
}
/******************/
/* STR */ /* store contents at address at level p */
/******************/
static void STR(void)
{
store[base()+cd.q] = *sp-- ;
}
/******************/
/* STRa */ /* store contents at address at level p */
/******************/
static void STRa(void)
{
store[base()+cd.q].va = (*(sp--)).va ;
}
#define STRc STRa
#define STRb STRa
#define STRr STR
#define STRs STR
/******************/
/* TRA */ /* trace of execuction */
/******************/
static void TRA(void)
{
trace = (cd.p==1) ; /* tra 1 の時 トレースON */
}
/******************/
/* TRC */ /* truncate */
/******************/
static void TRC(void)
{
(*sp).vi = (integer)(*sp).vr ;
}
/******************/
/* UDF */ /* UnDeFined instruction */
/******************/
static void UDF(void)
{
prerr(142,"未定義命令を実行しようとした") ;
}
/******************/
/* UJC */
/******************/
static void UJC(void)
{
prerr(51,"case文: 選択式の値に合致する選択定数がない") ;
}
/******************/
/* UJP */
/******************/
static void UJP(void)
{
pc = cd.q;
}
/******************/
/* UNI */
/******************/
static void UNI(void)
{
sp-- ;
(*sp).vs |= (*(sp+1)).vs ;
}
/******************/
/* XJP */
/******************/
static void XJP(void)
{
pc += (short)(*sp--).vi ;
}
/**********************************************************************/
/* P-code 別 処理エントリ表 */
/**********************************************************************/
static struct entry {
void (*func)(void) ;
} pcd[] = {
/* xx0 xx1 xx2 xx3 xx4 xx5 xx6 xx7 xx8 xx9 */
/*00x*/ LOD, LDO, STR, SRO, STO, CHK, IND, LDC, LDA, DEC,
/*01x*/ INC, MST, CUP, ENT, RET, UDF, IXA, EQU, NEQ, GEQ,
/*02x*/ GRT, LEQ, LES, UJP, FJP, XJP, EJP, LAP, ADI, ADR,
/*03x*/ SBI, SBR, SGS, FLT, FLO, TRC, NGI, NGR, SQI, SQR,
/*04x*/ ABI, ABR, NOT, AND, IOR, DIF, INT, UNI, INN, MOD,
/*05x*/ ODD, MPI, MPR, DVI, DVR, MOV, LCA, LAO, STP, ORD,
/*06x*/ CHR, UJC, MMS, MSI, CUI, BAS, LCI, CKA, TRA, ROU,
/*07x*/ NXT, NXD, UDF, UDF, UDF, NEW, DIS, PGE, EoF, EOL,
/*08x*/ RST, RWT, GET, PUT, WRS, WRB, WRI, WRR, WRC, WRF,
/*09x*/ WLN, RDI, RDR, RDC, RLN, TRS, TRW, TGT, TPT, ATN,
/*10x*/ SIN, COS, EXP, LOG, SQT, LDOa,LDOr,LDOs,LDOb,LDOc,
/*11x*/ UDF, UDF, CHKs,CHK, CHK, LODa,LODr,LODs,LODb,LODc,
/*12x*/ SROa,SROr,SROs,SROb,SROc,STRa,STRr,STRs,STRb,STRc,
/*13x*/ STOa,STOr,STOs,STOb,STOc,INDa,INDr,INDs,INDb,INDc,
/*14x*/ UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF,
/*15x*/ UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF,
/*16x*/ UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF,
/*17x*/ UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF,
/*18x*/ UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF,
/*19x*/ UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF,
/*20x*/ UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF,
/*21x*/ UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF,
/*22x*/ UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF,
/*23x*/ UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF,
/*24x*/ UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF, UDF,
/*25x*/ UDF, UDF, UDF, UDF, UDF, UDF
};
/***********************/
/* トレース処理 */
/***********************/
static void tracing(void)
{
printf("%4d[%3d %1d %6d] mp=%4d ep=%4d np=%4d stack[%4d]=%08lxH\n",
pc-1,cd.op,cd.p,cd.q, mp,ep,np,trans(sp),(*sp).vi);
}
/********************************/
/* P-code の 解釈実行処理 */
/********************************/
void interpret(void)
{
loop:
cd = store[pc++].vo ;
if(trace) tracing() ; /* トレースオプション有効 */
pcd[cd.op].func() ; /* opに対応した命令を実行 */
goto loop;
}